package cn.schoolwow.quickdao.module.operation.kit;

import cn.schoolwow.quickdao.domain.DAO;
import cn.schoolwow.quickdao.domain.database.dml.TransactionConsumer;
import cn.schoolwow.quickdao.domain.database.parent.UpgradeRequest;
import cn.schoolwow.quickdao.domain.exception.SQLRuntimeException;
import cn.schoolwow.quickdao.domain.operation.GenerateJavaSourceFileRequest;
import cn.schoolwow.quickdao.domain.transaction.Transaction;
import cn.schoolwow.quickdao.module.database.transaction.kit.TransactionInvocationHandler;
import cn.schoolwow.quickdao.module.initial.service.InitialDAOCompositeBusiness;
import cn.schoolwow.quickdao.module.operation.flow.ClearEntityTableFlow;
import cn.schoolwow.quickdao.module.operation.service.DatabaseUpgradeCompositeBusiness;
import cn.schoolwow.quickdao.module.operation.service.GenerateJavaSourceFileCompositeBusiness;
import cn.schoolwow.quickflow.QuickFlow;

import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.function.Consumer;

public class DAOOperationImpl implements DAOOperation {
    private QuickFlow quickFlow;

    public DAOOperationImpl(QuickFlow quickFlow) {
        this.quickFlow = quickFlow;
    }

    @Override
    public Transaction startTransaction() {
        TransactionInvocationHandler transactionInvocationHandler = new TransactionInvocationHandler(quickFlow);
        Transaction transactionProxy = (Transaction) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), new Class<?>[]{Transaction.class}, transactionInvocationHandler);
        return transactionProxy;
    }

    @Override
    public void startTransaction(TransactionConsumer transactionConsumer) {
        Transaction transaction = startTransaction();
        Connection connection = transaction.getTransactionConnection();
        try {
            transactionConsumer.transactionConsumer(transaction);
            connection.commit();
        } catch (Exception e) {
            try {
                connection.rollback();
            } catch (SQLException ex) {
                ex.printStackTrace();
            }
            throw new SQLRuntimeException(e);
        } finally {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void upgrade(String comment, Consumer<DAO> upgradeConsumer) {
        UpgradeRequest upgradeRequest = new UpgradeRequest();
        upgradeRequest.comment = comment;
        upgradeRequest.upgradeConsumer = upgradeConsumer;
        quickFlow.startFlow(new DatabaseUpgradeCompositeBusiness())
                .putInstanceData(upgradeRequest)
                .execute();
    }

    @Override
    public void upgrade(UpgradeRequest upgradeRequest) {
        quickFlow.startFlow(new DatabaseUpgradeCompositeBusiness())
                .putInstanceData(upgradeRequest)
                .execute();
    }

    @Override
    public void generateJavaSourceFile(GenerateJavaSourceFileRequest generateJavaSourceFileRequest) {
        quickFlow.startFlow(new GenerateJavaSourceFileCompositeBusiness())
                .putTemporaryData("generateJavaSourceFileRequest", generateJavaSourceFileRequest)
                .execute();
    }

    @Override
    public void initialDatabase() {
        quickFlow.startFlow(new InitialDAOCompositeBusiness())
                .putTemporaryData("dao", this)
                .execute();
    }

    @Override
    public void clearEntityTable() {
        quickFlow.startFlow(new ClearEntityTableFlow()).execute();
    }

}